package com.haixiaoke.flat.bill.controller;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.haixiaoke.auth.AuthCheck;
import com.haixiaoke.saas.account.yima.doman.*;
import com.haixiaoke.saas.account.yima.service.YiMaService;
import com.haixiaoke.saas.bill.domain.HouseBill;
import com.haixiaoke.saas.bill.service.IHouseBillService;
import com.haixiaoke.saas.common.config.WeChatConfig;
import com.haixiaoke.saas.common.config.YiMaConfig;
import com.haixiaoke.saas.common.constant.BillConstants;
import com.haixiaoke.saas.common.constant.WorkOrderConstants;
import com.haixiaoke.saas.common.constant.YiMaRequestTypeConstants;
import com.haixiaoke.saas.common.core.domain.AjaxResult;
import com.haixiaoke.saas.common.core.page.TableDataInfo;
import com.haixiaoke.saas.common.core.redis.RedisCache;
import com.haixiaoke.saas.common.enums.BillStateEnum;
import com.haixiaoke.saas.common.enums.HouseStateEnum;
import com.haixiaoke.saas.common.exception.ServiceException;
import com.haixiaoke.saas.common.weChat.domain.UnifiedOrder;
import com.haixiaoke.saas.common.weChat.service.WeChatService;
import com.haixiaoke.saas.contract.domain.Proprietor;
import com.haixiaoke.saas.contract.domain.ProxyService;
import com.haixiaoke.saas.contract.service.IProprietorService;
import com.haixiaoke.saas.contract.service.IProxyServiceService;
import com.haixiaoke.saas.department.domain.WechatAccount;
import com.haixiaoke.saas.department.service.IWechatAccountService;
import com.haixiaoke.saas.house.domain.House;
import com.haixiaoke.saas.house.service.IHouseService;
import com.haixiaoke.saas.system.BaseController;
import com.haixiaoke.saas.user.domain.UserConsumer;
import com.haixiaoke.saas.user.service.IUserConsumerService;
import com.haixiaoke.token.FrontTokenComponent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 入住账单Controller
 *
 * @author qixi
 * @date 2024-05-30
 */
@RestController
@RequestMapping("/front/flat/bill/house")
public class FlatHouseBillController extends BaseController {
    @Autowired
    private IHouseBillService houseBillService;

    @Autowired
    private FrontTokenComponent frontTokenComponent;

    @Autowired
    private WeChatService weChatService;
    @Autowired
    private IWechatAccountService wechatAccountService;
    @Autowired
    private WeChatConfig weChatConfig;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private IUserConsumerService userConsumerService;
    @Autowired
    private IHouseService houseService;
    @Autowired
    private IProxyServiceService proxyServiceService;
    @Autowired
    private YiMaConfig yiMaConfig;
    @Autowired
    private IProprietorService proprietorService;
    @Autowired
    private YiMaService yiMaService;

    /**
     * 查询入住账单列表
     */
    @GetMapping("/list")
    @AuthCheck
    public TableDataInfo list(HouseBill houseBill) {
        startPage();
        if (StrUtil.isEmpty(houseBill.getOrderId())) {
            throw new ServiceException("订单ID不能为空");
        }
        List<HouseBill> list = houseBillService.selectHouseBillList(houseBill);
        return getDataTable(list);
    }

    /**
     * 获取入住账单详细信息
     */
    @AuthCheck
    @GetMapping(value = "/{billId}")
    public AjaxResult getInfo(@PathVariable("billId") String billId) {
        return success(houseBillService.selectHouseBillByBillId(billId));
    }


    /**
     * 根据合同id获取入住账单
     */
    @GetMapping(value = "/contractId/{lesseeContractId}")
    public AjaxResult getHouseBillByContractId(@PathVariable("lesseeContractId") String lesseeContractId) {
        return success(houseBillService.selectHouseBillListByLesseeContractId(lesseeContractId));
    }


    /**
     * 根据合同id获取入住账单
     */
    // @AuthCheck
    @GetMapping(value = "/countOutstanding/{orderId}")
    public AjaxResult countOutstanding(@PathVariable("orderId") String orderId) {
        return success(houseBillService.selectOutstandingByOrderId(orderId));
    }


    /**
     * 入住账单支付
     */
    @AuthCheck
    @GetMapping(value = "/pay/{billId}/{payType}")
    public AjaxResult pay(@PathVariable("billId") String billId, @PathVariable("payType") String payType) {

        HouseBill houseBill = houseBillService.selectHouseBillByBillId(billId);
        if (houseBill == null) {
            return AjaxResult.error("账单不存在");
        }

        if (BillStateEnum.BILL_STATE_PAID.getValue().equals(houseBill.getPayState())
                || BillStateEnum.BILL_STATE_LOGOUT.getValue().equals(houseBill.getPayState())) {
            return error("账单状态异常，请刷新后再试");
        }

        // Object cacheObject = redisCache.getCacheObject(BillConstants.REDIS_HOUSE_BILL_KEY + billId);
        // if (cacheObject != null) {
        //     return error("请勿重复支付");
        // }

        String houseId = houseBill.getHouseId();
        House house = houseService.selectHouseByHouseId(houseId);
        if (ObjectUtil.isEmpty(house)) {
            return error("房源不存在");
        }
        String cooperationType = house.getCooperationType();

        UserConsumer userConsumer = userConsumerService.selectUserConsumerByUserId(frontTokenComponent.getUserIdNotNull());
        if (ObjectUtil.isEmpty(userConsumer) || StrUtil.isBlank(userConsumer.getOpenId())) {
            return error("用户数据异常");
        }
        String openId = userConsumer.getOpenId();

        // 缓存账单信息
        houseBill.setPayUserId(userConsumer.getUserId());
        houseBill.setPayUserName(userConsumer.getNickName());
        redisCache.setCacheObject(BillConstants.REDIS_HOUSE_BILL_KEY + houseBill.getBillId(), houseBill, 15, TimeUnit.MINUTES);

        if (StrUtil.equals(cooperationType, HouseStateEnum.COOPERATION_TYPE_COMMISSION.getValue())) {
            WechatAccount account = wechatAccountService.selectWechatAccountByTenantId(houseBill.getTenantId());
            if (ObjectUtil.isEmpty(account)) {
                return error("商家信息错误，请联系管理员");
            }
            UnifiedOrder unifiedOrder = getUnifiedOrder(openId, account, houseBill);

            // 选择支付方式
            if (BillConstants.HOUSE_BILL_PAYMENT_TYPE_WECHAT.equals(payType)){
                return weChatService.unifiedOrder(unifiedOrder);
            }else {
                String url = redisCache.getCacheObject(BillConstants.REDIS_HOUSE_BILL_NATIVE_PAY_REDIS_KEY + billId);
                if (StrUtil.isBlank(url)){
                    AjaxResult ajaxResult = weChatService.nativeOrder(unifiedOrder);
                    url = StrUtil.toString(ajaxResult.get("data"));
                    redisCache.setCacheObject(BillConstants.REDIS_HOUSE_BILL_NATIVE_PAY_REDIS_KEY + billId, url, 120, TimeUnit.MINUTES);
                }
                return AjaxResult.success("success", url);
            }
        } else {
            // 选择支付方式
            if (BillConstants.HOUSE_BILL_PAYMENT_TYPE_WECHAT.equals(payType)){
                YimaPayDto yimaPayDto = getYimaUnifiedPayDto(houseBill, house, userConsumer);
                return success(yiMaService.unifiedorder(yimaPayDto));
            }else {
                String url = redisCache.getCacheObject(BillConstants.REDIS_HOUSE_BILL_NATIVE_PAY_REDIS_KEY + billId);
                if (StrUtil.isBlank(url)){
                    YimaPayDto yimaPayDto = getYimaScanpaypayDto(houseBill, house, userConsumer);
                    url = ObjectUtil.toString(yiMaService.nativeOrder(yimaPayDto));
                    redisCache.setCacheObject(BillConstants.REDIS_HOUSE_BILL_NATIVE_PAY_REDIS_KEY + billId, url, 120, TimeUnit.MINUTES);
                }
                return AjaxResult.success("success", url);
            }

        }
    }

    private YimaPayDto getYimaUnifiedPayDto(HouseBill houseBill, House house, UserConsumer userConsumer) {
        Long proprietorUserId = house.getProprietorUserId();
        Proprietor proprietor = proprietorService.selectProprietorByUserId(proprietorUserId);
        if (proprietor == null) {
            throw new ServiceException("业主信息不存在");
        }

        GoodsDetail goodsDetail = new GoodsDetail();
        goodsDetail.setGoods_name("房屋管家-入住账单");
        goodsDetail.setGoods_id(houseBill.getBillId());
        goodsDetail.setQuantity(1L);
        BigDecimal cost = houseBill.getCost();
        long costInt = cost.multiply(BigDecimal.valueOf(100)).longValue();
        goodsDetail.setPrice(costInt);

        YimaPayDto yimaPayDto = new YimaPayDto();
        yimaPayDto.setRequestType(YiMaRequestTypeConstants.UNIFIEDORDER);
        yimaPayDto.setIsspid(yiMaConfig.getIsspid());
        yimaPayDto.setPosId(proprietor.getProprietorMobile());
        yimaPayDto.setStoreId(proprietor.getProprietorMobile());
        yimaPayDto.setPosSeq(houseBill.getBillId() + "_" + RandomUtil.randomNumbers(2));
        yimaPayDto.setSystemId(yiMaConfig.getSystemId());
        yimaPayDto.setDeviceIp(yiMaConfig.getDeviceIp());
        String memo = house.getPremisesAddress() + "-" + DateUtil.format(houseBill.getBillStartTime(), "yyyy-MM-dd") + "-" + DateUtil.format(houseBill.getBillEndTime(), "yyyy-MM-dd") + "入住账单";
        yimaPayDto.setMemo(memo);

        ExtendParams params = buildYmSplitInfo(houseBill, house);

        Map<String, Object> unifiedorderRequest = new HashMap<>();
        unifiedorderRequest.put("pay_type", "515");
        unifiedorderRequest.put("trade_type", "JSAPI");
        unifiedorderRequest.put("buyer_id", userConsumer.getOpenId());
        List<GoodsDetail> list = ListUtil.list(false, goodsDetail);
        unifiedorderRequest.put("goods_detail", JSONUtil.parseArray(list));
        unifiedorderRequest.put("tx_amt", costInt);
        unifiedorderRequest.put("notify_url", yiMaConfig.getNotifyUrl());
        unifiedorderRequest.put("extend_params", JSONObject.parseObject(JSONUtil.toJsonStr(params)));
        yimaPayDto.setUnifiedorderRequest(unifiedorderRequest);

        return yimaPayDto;
    }
    private YimaPayDto getYimaScanpaypayDto(HouseBill houseBill, House house, UserConsumer userConsumer) {
        Long proprietorUserId = house.getProprietorUserId();
        Proprietor proprietor = proprietorService.selectProprietorByUserId(proprietorUserId);
        if (proprietor == null) {
            throw new ServiceException("业主信息不存在");
        }

        GoodsDetail goodsDetail = new GoodsDetail();
        goodsDetail.setGoods_name("房屋管家-入住账单");
        goodsDetail.setGoods_id(houseBill.getBillId());
        goodsDetail.setQuantity(1L);
        BigDecimal cost = houseBill.getCost();
        long costInt = cost.multiply(BigDecimal.valueOf(100)).longValue();
        goodsDetail.setPrice(costInt);

        YimaPayDto yimaPayDto = new YimaPayDto();
        yimaPayDto.setRequestType(YiMaRequestTypeConstants.SCANPAY);
        yimaPayDto.setIsspid(yiMaConfig.getIsspid());
        yimaPayDto.setPosId(proprietor.getProprietorMobile());
        yimaPayDto.setStoreId(proprietor.getProprietorMobile());
        yimaPayDto.setPosSeq(houseBill.getBillId() + "_" + RandomUtil.randomNumbers(2));
        yimaPayDto.setSystemId(yiMaConfig.getSystemId());
        yimaPayDto.setDeviceIp(yiMaConfig.getDeviceIp());
        String memo = house.getPremisesAddress() + "-" + DateUtil.format(houseBill.getBillStartTime(), "yyyy-MM-dd") + "-" + DateUtil.format(houseBill.getBillEndTime(), "yyyy-MM-dd") + "入住账单";
        yimaPayDto.setMemo(memo);

        ExtendParams params = buildYmSplitInfo(houseBill, house);

        Map<String, Object> scanpayRequestRequest = new HashMap<>();
        scanpayRequestRequest.put("pay_type", "503");
        List<GoodsDetail> list = ListUtil.list(false, goodsDetail);
        scanpayRequestRequest.put("goods_detail", JSONUtil.parseArray(list));
        scanpayRequestRequest.put("tx_amt", costInt);
        scanpayRequestRequest.put("notify_url", yiMaConfig.getNotifyUrl());
        scanpayRequestRequest.put("extend_params", JSONObject.parseObject(JSONUtil.toJsonStr(params)));
        yimaPayDto.setScanpayRequest(scanpayRequestRequest);

        return yimaPayDto;
    }

    private ExtendParams buildYmSplitInfo(HouseBill houseBill, House house) {
        Long proprietorUserId = house.getProprietorUserId();
        ProxyService proxyService = proxyServiceService.selectProxyServiceByConUserId(proprietorUserId);
        if (ObjectUtil.isEmpty(proxyService)) {
            throw new ServiceException("业主信息不存在");
        }

        ExtendParams extendParams = new ExtendParams();
        // N：不分账
        // R：实时分账
        // D：延时分账
        extendParams.setSplit_flag("R");

        // 账单收取百分比
        BigDecimal serviceCharge = house.getServiceCharge();
        BigDecimal cost = houseBill.getCost();
        SplitInfo splitInfo = new SplitInfo();
        String chargeType = house.getChargeType();

        // 翼码手续费 0.3%
        BigDecimal handlingCharge = cost.multiply(BigDecimal.valueOf(0.003)).setScale(2, RoundingMode.HALF_UP);

        cost = cost.subtract(handlingCharge);
        // 随账单收费
        if (HouseStateEnum.CHARGE_TYPE_BILL.getValue().equals(chargeType)) {
            // 机构自留金额
            BigDecimal orgCost = cost.multiply(serviceCharge.divide(BigDecimal.valueOf(100))).setScale(2, RoundingMode.HALF_UP);
            BigDecimal proprietorCost = cost.subtract(orgCost).setScale(2, RoundingMode.HALF_UP);
            // 金额分为单位
            splitInfo.setKeep_amt(ObjectUtil.toString(orgCost.add(handlingCharge).multiply(BigDecimal.valueOf(100)).intValue()));

            // 业主所得
            SplitList splitList = new SplitList();
            splitList.setMerchant_id(proxyService.getYmMerchantId().toString());
            splitList.setDiv_amt(ObjectUtil.toString(proprietorCost.multiply(BigDecimal.valueOf(100)).intValue()));
            splitInfo.setSplit_list(ListUtil.list(false, splitList));


        } else {
            // 一次性服务费 企业不收取
            splitInfo.setKeep_amt(ObjectUtil.toString(handlingCharge.multiply(BigDecimal.valueOf(100)).intValue()));
            // 业主所得
            SplitList splitList = new SplitList();
            splitList.setMerchant_id(proxyService.getYmMerchantId().toString());
            splitList.setDiv_amt(ObjectUtil.toString(cost.multiply(BigDecimal.valueOf(100)).intValue()));
            splitInfo.setSplit_list(ListUtil.list(false, splitList));
        }
        extendParams.setSplit_info(splitInfo);
        return extendParams;
    }

    private UnifiedOrder getUnifiedOrder(String openId, WechatAccount account, HouseBill houseBill) {
        UnifiedOrder unifiedOrder = new UnifiedOrder();
        unifiedOrder.setAppId(weChatConfig.getAppId());
        unifiedOrder.setOpenId(openId);
        unifiedOrder.setAccountId(account.getAccountId());
        unifiedOrder.setAccountApiKey(account.getAccountApiKey());
        unifiedOrder.setAttach(account.getTenantId());
        unifiedOrder.setOutTradeNo(houseBill.getBillId()+"_"+RandomUtil.randomNumbers(2));
        BigDecimal totalFee = houseBill.getCost();
        unifiedOrder.setCallBackUrl(weChatConfig.getHouseBillPayCallBackUrl());
        unifiedOrder.setBody("房屋管家-入住账单支付");
        // todo: 2024-6-5 金额写死
        unifiedOrder.setTotalFee(/*totalFee.multiply(BigDecimal.valueOf(100)).intValue()*/1);
        return unifiedOrder;
    }


}
